package com.srdl.code.generate;

import com.srdl.code.generate.config.DataSourceConfig;
import com.srdl.code.generate.config.GlobalConfig;
import com.srdl.code.generate.po.TableField;
import com.srdl.code.generate.po.TableInfo;
import com.srdl.code.generate.utils.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;


public class CodeGenerate implements ICallBack {

    private static Logger logger = LoggerFactory.getLogger(CodeGenerate.class);


    private List<TableInfo> tableInfoList;
    private TableInfo tableInfo;
    private GlobalConfig globalConfig;
    private DataSourceConfig dataSourceConfig;

    public CodeGenerate() {
    }

    public CodeGenerate(GlobalConfig globalConfig, DataSourceConfig dataSourceConfig) {
        this.globalConfig = globalConfig;
        this.dataSourceConfig = dataSourceConfig;
    }

    @Override
    public Map<String, Object> execute() {
        Map data = new HashMap();
        data.put("entityPackage", globalConfig.getPojoPackage());
        data.put("controllerPackage", globalConfig.getControllerPackage());
        data.put("servicePackage", globalConfig.getServicePackage());
        data.put("mapperPackage", globalConfig.getMapperPackage());
        data.put("serviceImplPackage", globalConfig.getServiceImplPackage().replace("/", "."));
        data.put("repositoryPackage", globalConfig.getRepositoryPackage());
        //移除表前缀，表名之间的下划线，得到实体类型
        String entity = CommonUtils.getNoUnderlineStr(CommonUtils.removePrefix(tableInfo.getName().toLowerCase(), globalConfig.getPrefix()));
        data.put("entity", StringUtils.capitalize(entity));//实体名称
        data.put("author", globalConfig.getAuthor());//创建作者
        data.put("date", CommonUtils.getFormatTime("yyyy-MM-dd", new Date()));//创建时间
        data.put("table", tableInfo);//表信息
        data.put("bao", globalConfig.getBao());
        data.put("port", globalConfig.getProp());
        data.put("driver", dataSourceConfig.getDriverName());
        data.put("url", dataSourceConfig.getUrl());
        data.put("username", dataSourceConfig.getUsername());
        data.put("password", dataSourceConfig.getPassword());
        String[][] strings = new String[tableInfo.getFields().size()][2];
        if (globalConfig.getType().equals("ssm")) {
            List<String> list = new ArrayList<String>();
            List<String> list2 = new ArrayList<String>();
            int num = 0;
            for (TableField field : tableInfo.getFields()) {
                list.add(field.getName());
                list2.add(field.getName());
                strings[num][0] = CommonUtils.getNoUnderlineStr(field.getName());
                strings[num][1] = field.getName();
                num++;
            }
            data.put("dataCol", list2);//原始列名
            list.remove(0);
            data.put("data2", list);
        }
        data.put("sss", strings);
        boolean isKeyflag = false;
        for (TableField field : tableInfo.getFields()) {
            if (field.isKeyIdentityFlag()) {//获取主键字段信息
                data.put("tbKey", field.getName());
                data.put("tbKeyType", field.getPropertyType());
                isKeyflag = true;
                break;
            }
        }
        if (!isKeyflag) {
            throw new RuntimeException(String.format("[%s]表缺少主键，不能没有主键", tableInfo.getName()));
        }
        return data;
    }


    /**
     * 生成代码文件
     *
     * @return
     */
    public boolean generateToFile() {
        initConfig();
        if (globalConfig.getType().equals("ssh")) {
            for (TableInfo tableInfo : tableInfoList) {
                this.tableInfo = tableInfo;//当前需要生成的表
                logger.info("------Code----Generation----[单表模型:" + tableInfo.getName() + "]------- 生成中。。。");
                try {
                    CodeFactory codeFactory = new CodeFactory();
                    codeFactory.setCallBack(this);
                    codeFactory.setGlobalConfig(globalConfig);
                    codeFactory.invoke("ssh/entityTemplate.ftl", "pojo");
                    codeFactory.invoke("ssh/jpaTemplate.ftl", "jpa");
                    codeFactory.invoke("ssh/serviceTemplate.ftl", "service");
                    codeFactory.invoke("ssh/serviceImplTemplate.ftl", "serviceImpl");
                    codeFactory.invoke("ssh/controllerTemplate.ftl", "controller");
                    logger.info("-------Code----Generation-----[单表模型：" + tableInfo.getName() + "]------ 生成完成。。。");
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.info("-------Code----Generation-----[单表模型：" + tableInfo.getName() + "]------ 生成失败。。。");
                    return false;
                }
            }
            try {
                logger.info("------Code----Generation----[application.yml]------- 生成中。。。");
                CodeFactory codeFactory = new CodeFactory();
                codeFactory.setCallBack(this);
                codeFactory.setGlobalConfig(globalConfig);
                codeFactory.invoke("ssh/applicationTemplate.ftl", "application");
                logger.info("------Code----Generation----[application.yml]------- 生成完成。。。");
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("------Code----Generation----[application.yml]------- 生成失败。。。");
                return false;
            }
            try {
                logger.info("------Code----Generation----[Springboot.java]------- 生成中。。。");
                CodeFactory codeFactory = new CodeFactory();
                codeFactory.setCallBack(this);
                codeFactory.setGlobalConfig(globalConfig);
                codeFactory.invoke("ssh/springboot.ftl", "springboot");
                logger.info("------Code----Generation----[Springboot.java]------- 生成完成。。。");
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("------Code----Generation----[Springboot.java]------- 生成失败。。。");
                return false;
            }
        } else if (globalConfig.getType().equals("ssm")) {
            for (TableInfo tableInfo : tableInfoList) {
                this.tableInfo = tableInfo;//当前需要生成的表
                logger.info("------Code----Generation----[单表模型:" + tableInfo.getName() + "]------- 生成中。。。");
                try {
                    CodeFactory codeFactory = new CodeFactory();
                    codeFactory.setCallBack(this);
                    codeFactory.setGlobalConfig(globalConfig);
                    codeFactory.invoke("ssm/entityTemplate.ftl", "pojo");
                    codeFactory.invoke("ssm/mapperXmlTemplate.ftl", "mapperXml");
                    codeFactory.invoke("ssm/mapperTemplate.ftl", "mapper");
                    codeFactory.invoke("ssm/serviceTemplate.ftl", "service");
                    codeFactory.invoke("ssm/serviceImplTemplate.ftl", "serviceImpl");
                    codeFactory.invoke("ssm/controllerTemplate.ftl", "controller");
                    logger.info("-------Code----Generation-----[单表模型：" + tableInfo.getName() + "]------ 生成完成。。。");
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.info("-------Code----Generation-----[单表模型：" + tableInfo.getName() + "]------ 生成失败。。。");
                    return false;
                }
            }
            try {
                logger.info("------Code----Generation----[application.yml]------- 生成中。。。");
                CodeFactory codeFactory = new CodeFactory();
                codeFactory.setCallBack(this);
                codeFactory.setGlobalConfig(globalConfig);
                codeFactory.invoke("ssm/applicationTemplate.ftl", "application");
                logger.info("------Code----Generation----[application.yml]------- 生成完成。。。");
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("------Code----Generation----[application.yml]------- 生成失败。。。");
                return false;
            }
            try {
                logger.info("------Code----Generation----[mybitisConfig.xml]------- 生成中。。。");
                CodeFactory codeFactory = new CodeFactory();
                codeFactory.setCallBack(this);
                codeFactory.setGlobalConfig(globalConfig);
                codeFactory.invoke("ssm/mybitisConfig.ftl", "mybitisConfig");
                logger.info("------Code----Generation----[mybitisConfig.xml]------- 生成完成。。。");
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("------Code----Generation----[mybitisConfig.xml]------- 生成失败。。。");
                return false;
            }
            try {
                logger.info("------Code----Generation----[Springboot.java]------- 生成中。。。");
                CodeFactory codeFactory = new CodeFactory();
                codeFactory.setCallBack(this);
                codeFactory.setGlobalConfig(globalConfig);
                codeFactory.invoke("ssm/springboot.ftl", "springboot");
                logger.info("------Code----Generation----[Springboot.java]------- 生成完成。。。");
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("------Code----Generation----[Springboot.java]------- 生成失败。。。");
                return false;
            }
        }
        return true;
    }

    private void initConfig() {
        if (dataSourceConfig == null) {
            throw new RuntimeException("dataSourceConfig is null");
        }
        if (globalConfig == null) {
            throw new RuntimeException("globalConfig is null");
        }
        if (globalConfig.getTableNames().length < 1) {
            String[] str = new String[dataSourceConfig.getTableNames().size()];
            int num = 0;
            for (String item : dataSourceConfig.getTableNames()) {
                str[num] = item;
                num++;
            }
            globalConfig.setTableNames(str);

        }
        tableInfoList = dataSourceConfig.getTablesInfo(globalConfig.getTableNames());
    }
}
